package com.zoe.onelink.upms.common.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.zoe.onelink.upms.common.constants.SecurityConstants;
import com.zoe.onelink.upms.common.constants.SystemConstants;
import com.zoe.onelink.upms.common.entity.UserDetailsInfo;
import com.zoe.onelink.upms.common.entity.UserInfo;
import com.zoe.onelink.upms.common.service.OneLinkTokenStore;
import lombok.experimental.UtilityClass;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2018</p>
 * <p>公司: 智业软件</p>
 *
 * @author LinHongKai
 * @date 2022-02-25 21:26
 */
@UtilityClass
public class UpmsUtils {

    private final String Bearer = OAuth2AccessToken.BEARER_TYPE;

    private final String bearer = "bearer";

    private final String Authorization = "Authorization";

    private static OneLinkTokenStore oneLinkTokenStore = SpringUtil.getBean(OneLinkTokenStore.class);


    /**
     * 获取当前登录的用户
     * @return
     */
    public UserInfo getUser() {
        Authentication authentication = getAuthentication();
        if (authentication == null) {
            return null;
        }
        return getUser(authentication);
    }


    /**
     * 获取当前登录的用户的权限标识集合
     * @return
     */
    public List<String> getUserPermissions() {
        String token = getToken();
        return oneLinkTokenStore.readPermission(token);
    }


    /**
     * 获取请求头中的token
     * @return
     */
    public String getToken() {
        HttpServletRequest request = getHttpRequest();
        if(request == null){
            return null;
        }

        // 先从请求头中获取onelinkToken
        String tokenValue = request.getHeader(SecurityConstants.HEADER_TOKEN);
        if(StrUtil.isNotEmpty(tokenValue)){
            return tokenValue;
        }

        // 再尝试从传参中获取onelinkToken
        tokenValue = request.getParameter(SecurityConstants.HEADER_TOKEN);
        if(StrUtil.isNotEmpty(tokenValue)){
            return tokenValue;
        }

        // 最后尝试从标准格式的授权头中获取onelinkToken
        tokenValue = request.getHeader(Authorization);
        if(StrUtil.isNotEmpty(tokenValue)){
            tokenValue = tokenValue.replace(Bearer, StrUtil.EMPTY).trim();
            tokenValue = tokenValue.replace(bearer, StrUtil.EMPTY).trim();
            return tokenValue;
        }
        return null;
    }


    /**
     * 获取请求头中的token
     * @return
     */
    public String getToken(HttpServletRequest request) {
        String tokenValue = request.getHeader(SecurityConstants.HEADER_TOKEN);
        if(StrUtil.isNotEmpty(tokenValue)){
            return tokenValue;
        }
        tokenValue = request.getHeader(Authorization);

        if(StrUtil.isEmpty(tokenValue)){
            return null;
        }
        tokenValue = tokenValue.replace(Bearer, StrUtil.EMPTY).trim();
        tokenValue = tokenValue.replace(bearer, StrUtil.EMPTY).trim();
        return tokenValue;
    }


    public String getParamValue(String paramName){
        HttpServletRequest request = getHttpRequest();
        return request.getParameter(paramName);
    }


    public HttpServletRequest getHttpRequest(){
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(servletRequestAttributes == null){
            return null;
        }
        return servletRequestAttributes.getRequest();
    }


    private Authentication getAuthentication() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication != null && !SystemConstants.ANONYMOUS_USER_USERNAME.equals(authentication.getPrincipal())){
            return authentication;
        }

        // 兼容，在代码上误加了@InnerUrl注解的，但是前端请求有带token，而代码中需要获取当前用户的
        String token = getToken();
        if(StringUtils.isEmpty(token)){
            return null;
        }
        return oneLinkTokenStore.readAuthentication(token);
    }


    private UserInfo getUser(Authentication authentication) {
        Object principal = authentication.getPrincipal();
        if(principal == null) {
            return null;
        }
        if (principal instanceof UserDetailsInfo) {
            return new UserInfo((UserDetailsInfo) principal);
        }
        return null;
    }


    private HttpServletResponse getResponse() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
    }
}
